class Left {
  static of (value) {
    return new Left(value)
  }

  constructor (value) {
    this._value = value
  }

  map (fn) {
    return this
  }
}

class Right {
  static of (value) {
    return new Right(value)
  }

  constructor (value) {
    this._value = value
  }

  map (fn) {
    return Right.of(fn(this._value))
  }
}

let r1 = Right.of(12)
.map(x => x + 2)
console.log(r1)
let r2 = Left.of(12) // Right { _value: 14 }
.map(x => x + 2)
console.log(r2) // Left { _value: 12 }

function parseJSON (str) {
  try {
    return Right.of(JSON.parse(str))
  } catch (e) {
    return Left.of({error: e.message})
  }
}

let r3 = parseJSON('{name: jal}')
console.log(r3) // Left { _value: { error: 'Unexpected token n in JSON at position 1' } }
let r4 = parseJSON('{"name": "jal"}')
console.log(r4) // Right { _value: { name: 'jal' } }
let r5 = r4.map(x => x.name.toUpperCase())
console.log(r5) // Right { _value: 'JAL' }